#include "Common.h"
#include "WindowsHeader.h"

namespace Audio
{
	namespace WindowsPlatform
	{

/*************************************************
*		WindowsAudioDevice
**************************************************/

		WindowsAudioDevice::WindowsAudioDevice()
			:xaudio2(NULL)
			,masteringVoice(NULL)
			,xaudio2Callback(NULL)
			,audioDeviceCallback(NULL)
		{
			//Init();
		}
		WindowsAudioDevice::~WindowsAudioDevice()
		{
			Destroy();
		}

		void WindowsAudioDevice::Init()
		{
			HRESULT hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );

			if(AUD_FAILED(hr))
			{
				throw APIFailedException(L"CoInitializeEx");
			}

			if(AUD_FAILED(hr = XAudio2Create( &xaudio2, 0) ) )
			{
				throw APIFailedException(L"XAudio2Create");
			}

			if( AUD_FAILED(hr = xaudio2->CreateMasteringVoice( 
				&masteringVoice
				, XAUDIO2_DEFAULT_CHANNELS
				, XAUDIO2_DEFAULT_SAMPLERATE
				) ) )
			{
				throw APIFailedException(L"IXAudio2::CreateMasteringVoice");
			}

			xaudio2Callback = new XAudio2VoiceCallback(this);
		}

		void WindowsAudioDevice::Destroy()
		{
			masteringVoice->DestroyVoice();
			xaudio2->Release();
		}

		IVoice* WindowsAudioDevice::CreateVoice(void* info, UINT32 infoSize)
		{
			if(info == NULL || infoSize == 0)
			{
				throw NullPointerException();
			}

			IXAudio2SourceVoice* sourceVoice = NULL;
			if(AUD_FAILED(xaudio2->CreateSourceVoice(&sourceVoice
				, (WAVEFORMATEX*)info
				, 0
				, XAUDIO2_DEFAULT_FREQ_RATIO
				, xaudio2Callback
				, NULL
				, NULL)))
			{
				throw APIFailedException(L"IXAudio2::CreateSourceVoice");
			}
			return new WindowsVoice(sourceVoice);
		}

		void  WindowsAudioDevice::DestroyVoice(IVoice*& voice)
		{
			delete voice;
			voice = NULL;
		}

		void WindowsAudioDevice::SetDeviceCallback(IAudioDeviceCallBack* callback)
		{
			audioDeviceCallback = callback;
		}
		IAudioDeviceCallBack* WindowsAudioDevice::GetDeviceCallback()
		{
			return audioDeviceCallback;
		}


/*************************************************
*		XAudio2VoiceCallback
**************************************************/

		void XAudio2VoiceCallback::OnStreamEnd()
		{
			if(device->GetDeviceCallback())
			{
				device->GetDeviceCallback()->OnStreamEnd(NULL);
			}
		}
		void XAudio2VoiceCallback::OnVoiceProcessingPassEnd()
		{

		}
		void XAudio2VoiceCallback::OnVoiceProcessingPassStart(UINT32 SamplesRequired)
		{

		}
		void XAudio2VoiceCallback::OnBufferEnd(void * pBufferContext)
		{
			if(device->GetDeviceCallback())
			{
				device->GetDeviceCallback()->OnNeedMoreData(pBufferContext);
			}
		}
		void XAudio2VoiceCallback::OnBufferStart(void * pBufferContext)
		{
			
		}
		void XAudio2VoiceCallback::OnLoopEnd(void * pBufferContext)
		{
			
		}
		void XAudio2VoiceCallback::OnVoiceError(void * pBufferContext, HRESULT Error)
		{
			if(device->GetDeviceCallback())
			{
				device->GetDeviceCallback()->OnVoiceError(pBufferContext);
			}
		}

	}
}
